package com.university.report.user.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.university.report.common.result.Result;

import com.university.report.common.result.ResultCodeEnum;
import com.university.report.common.result.ResultCodeEnum;
import com.university.report.common.utils.JSONAuthentication;
import com.university.report.common.utils.JwtUtil;
import com.university.report.model.entity.UserAccount;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName health_report
 * @Author Jinondo
 * @Date 2021/6/16 18:21
 */
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {

    /**
     * 获取redisTemplate
     */
    RedisTemplate redisTemplate2;

    /**
     * 获取授权管理
     */
    private AuthenticationManager authenticationManager;

    public JWTLoginFilter(AuthenticationManager authenticationManager,RedisTemplate redisTemplate2) {
        this.redisTemplate2 = redisTemplate2;
        this.authenticationManager = authenticationManager;
        /**
         *  后端登陆接口 对登陆路径放行
         */
        super.setFilterProcessesUrl("/auth/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req,
                                                HttpServletResponse res) {
        try {
            UserAccount user = new ObjectMapper()
                    .readValue(req.getInputStream(), UserAccount.class);

            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUsername(),
                            user.getPassword(),
                            new ArrayList<>())
            );
        } catch (IOException e) {
            logger.error(e.getMessage());
            return  null;
        }
    }

    @Override
    /**
     * 用户登陆成功之后验证
     */
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException, ServletException {
        UserAccount userEntity = (UserAccount) authResult.getPrincipal();
        String jwtToken = JwtUtil.generateJsonWebToken(userEntity);
        String currentTime = String.valueOf(System.currentTimeMillis());
        String accesskey = JwtUtil.ACCESS_TOKEN + ":" + jwtToken;

        //往拼接存到redis中的Key存value值
        redisTemplate2.opsForValue().set(accesskey,currentTime);
        //设置redis key的过期时间 2天
        redisTemplate2.expire(accesskey,2, TimeUnit.DAYS);
        response.addHeader("token", jwtToken);
        Result result = Result.ok("登录成功");
        JSONAuthentication.writeJSON(request,response,result);
    }


/*    SpringSecurity的异常处理是在过滤器中进行的，我们在 AbastrctAuthenticationProcessingFilter 中找到了对 Authentication 的处理：


    在 doFilter() 中，捕获 AuthenticationException 异常，并交给 unsuccessfulAuthentication() 处理。
    处理的大致流程为：
    –> AbstractAuthenticationProcessingFilter.doFilter()
    –> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()
    –> SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()
    –> SimpleUrlAuthenticationFailureHandler.saveException()

    */

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        Result result;
        if (e instanceof AccountExpiredException) {
            //账号过期
            result = Result.fail(ResultCodeEnum.USER_ACCOUNT_EXPIRED);
        } else if (e instanceof BadCredentialsException) {
            //密码错误
            result = Result.fail(ResultCodeEnum.USER_CREDENTIALS_ERROR);
        } else if (e instanceof CredentialsExpiredException) {
            //密码过期
            result = Result.fail(ResultCodeEnum.USER_CREDENTIALS_EXPIRED);
        } else if (e instanceof DisabledException) {
            //账号不可用
            result = Result.fail(ResultCodeEnum.USER_ACCOUNT_DISABLE);
        } else if (e instanceof LockedException) {
            //账号锁定
            result = Result.fail(ResultCodeEnum.USER_ACCOUNT_LOCKED);
        } else if (e instanceof InternalAuthenticationServiceException) {
            //用户不存在
            result = Result.fail(ResultCodeEnum.USER_ACCOUNT_NOT_EXIST);
        }else{
            //其他错误
            result = Result.fail(ResultCodeEnum.FAIL);
        }
        //输出
        JSONAuthentication.writeJSON(request, response, result);
    }
}
